home *** CD-ROM | disk | FTP | other *** search
/ PC World 2007 June / PCWorld_2007-06_cd.bin / v cisle / tclock / tclocklight-040702-3.exe / source / dll / draw.c < prev    next >
C/C++ Source or Header  |  2004-06-29  |  13KB  |  501 lines

  1. /*-------------------------------------------------------------
  2.   draw.c : drawing the clock
  3.   (C) 1997-2003 Kazuto Sato
  4.   Please read readme.txt about the license.
  5.   
  6.   Written by Kazubon, Nanashi-san
  7. ---------------------------------------------------------------*/
  8.  
  9. #include "tcdll.h"
  10. #include "newapi.h"
  11.  
  12. /* Globals */
  13.  
  14. void LoadDrawingSetting(HWND hwnd);
  15. void ClearDrawing(void);
  16. void ClearClockDC(void);
  17. HDC GetClockBackDC(void);
  18. void OnPaint(HWND hwnd, HDC hdc, const SYSTEMTIME* pt);
  19. LRESULT OnCalcRect(HWND hwnd);
  20. void CreateClockDC(HWND hwnd);
  21.  
  22. BOOL g_bFitClock = FALSE; // Fit clock to tray
  23.  
  24. /* Statics */
  25.  
  26. static void GetClockTextSize(HDC hdc, const TEXTMETRIC* ptm,
  27.     const wchar_t* str, int *wout, int *hout);
  28. static void DrawClock(HWND hwnd, HDC hdc, const SYSTEMTIME* pt);
  29. static void CopyClockBack(HWND hwnd, HDC hdcDest, HDC hdcSrc, int w, int h);
  30. static void FillClock(HWND hwnd, HDC hdc, const RECT *prc);
  31. static void GradientFillClock(HDC hdc, const RECT* prc,
  32.     COLORREF col1, COLORREF col2, DWORD grad);
  33.  
  34. static HDC      m_hdcClock = NULL;      // offscreen DC
  35. static HBITMAP  m_hbmpClock = NULL;     // BMP for offscreen DC
  36. static HDC      m_hdcClockBack = NULL;  // offscreen DC of background
  37. static HBITMAP  m_hbmpClockBack = NULL; // BMP for offscreen DC of background
  38. static HFONT    m_hFont = NULL;         // font handle
  39. static BOOL     m_fillbackcolor = TRUE; // fill background
  40. static COLORREF m_colback, m_colback2, m_colfore; // colors
  41. static ULONG    m_grad = GRADIENT_FILL_RECT_H; // GradientFill direction
  42. static BOOL     m_bFillTray;            // Paint tray background
  43. static int m_dwidth = 0, m_dheight = 0; // to add pixels to width and height
  44. static int      m_dvpos = 0;            // to add pixels to vertical position
  45. static int      m_dlineheight = 0;      // to add pixels to line height
  46. static int      m_nTextPos = 0;         // alignment
  47. static int      m_ClockWidth = -1;      // to save clock width
  48.  
  49.  
  50. /*------------------------------------------------
  51.   read settings and initialize
  52. --------------------------------------------------*/
  53. void LoadDrawingSetting(HWND hwnd)
  54. {
  55.     char fontname[80];
  56.     int size, langid, codepage;
  57.     LONG weight, italic;
  58.     
  59.     /* ------- colors ------------- */
  60.     
  61.     m_fillbackcolor = GetMyRegLong(NULL, "UseBackColor",
  62.         g_bVisualStyle? FALSE: TRUE);
  63.     
  64.     m_colback = GetMyRegLong(NULL, "BackColor",
  65.         0x80000000 | COLOR_3DFACE);
  66.     
  67.     if((!g_winver&WINXP) && m_fillbackcolor == FALSE)
  68.     {
  69.         m_fillbackcolor = TRUE;
  70.         m_colback = 0x80000000 | COLOR_3DFACE;
  71.     }
  72.     
  73.     m_colback2 = m_colback;
  74.     if((g_winver&WIN98) || (g_winver&WIN2000))
  75.     {
  76.         if(GetMyRegLong(NULL, "UseBackColor2", TRUE))
  77.             m_colback2 = GetMyRegLong(NULL, "BackColor2", m_colback);
  78.         m_grad = GetMyRegLong(NULL, "GradDir", GRADIENT_FILL_RECT_H);
  79.     }
  80.     
  81.     m_bFillTray = FALSE;
  82.     if(m_fillbackcolor && ((g_winver&WINME) || (g_winver&WIN2000)))
  83.         m_bFillTray = GetMyRegLong(NULL, "FillTray", FALSE);
  84.     
  85.     m_colfore = GetMyRegLong(NULL, "ForeColor", 
  86.         0x80000000 | COLOR_BTNTEXT);
  87.     
  88.     /* ------- font ------------- */
  89.     
  90.     GetMyRegStr(NULL, "Font", fontname, 80, "");
  91.     
  92.     if(fontname[0] == 0)
  93.     {
  94.         HFONT hfont;
  95.         LOGFONT lf;
  96.         hfont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
  97.         if(hfont)
  98.         {
  99.             GetObject(hfont, sizeof(lf), (LPVOID)&lf);
  100.             strcpy(fontname, lf.lfFaceName);
  101.         }
  102.         else strcpy(fontname, "System");
  103.     }
  104.     
  105.     size = GetMyRegLong(NULL, "FontSize", 9);
  106.     if(size == 0) size = 9;
  107.     weight = GetMyRegLong(NULL, "Bold", 0);
  108.     if(weight) weight = FW_BOLD;
  109.     else weight = 0;
  110.     italic = GetMyRegLong(NULL, "Italic", 0);
  111.     
  112.     if(m_hFont) DeleteObject(m_hFont);
  113.     
  114.     langid = GetMyRegLong(NULL, "Locale", (int)GetUserDefaultLangID());
  115.     codepage = GetCodePage(langid);
  116.     
  117.     // font.c
  118.     m_hFont = CreateMyFont(fontname, size, weight, italic, codepage);
  119.     
  120.     /* ------- size and position ------------- */
  121.     
  122.     m_nTextPos = GetMyRegLong(NULL, "TextPos", 0);
  123.     m_dheight = (int)(short)GetMyRegLong(NULL, "ClockHeight", 0);
  124.     m_dwidth = (int)(short)GetMyRegLong(NULL, "ClockWidth", 0);
  125.     m_dvpos = (int)(short)GetMyRegLong(NULL, "VertPos", 0);
  126.     m_dlineheight = (int)(short)GetMyRegLong(NULL, "LineHeight", 0);
  127.     
  128.     g_bFitClock = FALSE;
  129.     if(g_winver&WINXP)
  130.         g_bFitClock = GetMyRegLong(NULL, "FitClock", TRUE);
  131.     
  132.     m_ClockWidth = -1;
  133. }
  134.  
  135. /*------------------------------------------------
  136.   clear up resouces
  137. --------------------------------------------------*/
  138. void ClearDrawing(void)
  139. {
  140.     if(m_hFont) DeleteObject(m_hFont);
  141.     m_hFont = NULL;
  142.     
  143.     ClearClockDC();
  144. }
  145.  
  146. /*------------------------------------------------
  147.   delete offscreen DC and bitmap
  148. --------------------------------------------------*/
  149. void ClearClockDC(void)
  150. {
  151.     m_ClockWidth = -1;
  152.     
  153.     if(m_hdcClock) DeleteDC(m_hdcClock); 
  154.     m_hdcClock = NULL;
  155.     if(m_hbmpClock) DeleteObject(m_hbmpClock);
  156.     m_hbmpClock = NULL;
  157.     
  158.     if(m_hdcClockBack) DeleteDC(m_hdcClockBack); 
  159.     m_hdcClockBack = NULL;
  160.     if(m_hbmpClockBack) DeleteObject(m_hbmpClockBack);
  161.     m_hbmpClockBack = NULL;
  162. }
  163.  
  164. /*------------------------------------------------
  165.    return m_hdcClockBack - used in traynotify.c
  166. --------------------------------------------------*/
  167. HDC GetClockBackDC(void)
  168. {
  169.     return m_hdcClockBack;
  170. }
  171.  
  172. /*------------------------------------------------
  173.   WM_PAINT message
  174. --------------------------------------------------*/
  175. void OnPaint(HWND hwnd, HDC hdc, const SYSTEMTIME* pt)
  176. {
  177.     DrawClock(hwnd, hdc, pt);
  178. }
  179.  
  180. /*------------------------------------------------
  181.   return size of clock
  182.   high-order word: height, low-order word: width
  183. --------------------------------------------------*/
  184. LRESULT OnCalcRect(HWND hwnd)
  185. {
  186.     TEXTMETRIC tm;
  187.     HDC hdc;
  188.     HFONT hOldFont;
  189.     wchar_t s[BUFSIZE_FORMAT+BUFSIZE_DISP*2];
  190.     int wclock, hclock;
  191.     
  192.     if(!(GetWindowLong(hwnd, GWL_STYLE) & WS_VISIBLE))
  193.         return 0;
  194.     
  195.     hdc = GetDC(hwnd);
  196.     if(m_hFont) hOldFont = SelectObject(hdc, m_hFont);
  197.     GetTextMetrics(hdc, &tm);
  198.     
  199.     if(g_sdisp2[0]) wcscpy(s, g_sdisp2);
  200.     else if(g_sdisp1[0]) wcscpy(s, g_sdisp1);
  201.     else MakeFormat(s, NULL, NULL, BUFSIZE_FORMAT);
  202.     
  203.     if(g_scat1[0]) wcscat(s, g_scat1);
  204.     if(g_scat2[0]) wcscat(s, g_scat2);
  205.     
  206.     GetClockTextSize(hdc, &tm, s, &wclock, &hclock);
  207.     
  208.     wclock += tm.tmAveCharWidth * 2 + m_dwidth;
  209.     hclock += (tm.tmHeight - tm.tmInternalLeading) / 2 + m_dheight;
  210.     if(hclock < 4) hclock = 4;
  211.     
  212.     if(wclock > m_ClockWidth) m_ClockWidth = wclock;
  213.     
  214.     if(g_bFitClock)
  215.     {
  216.         RECT rcTray, rcTaskbar;
  217.         
  218.         GetWindowRect(GetParent(hwnd), &rcTray);
  219.         GetClientRect(GetParent(GetParent(hwnd)), &rcTaskbar);
  220.         
  221.         // horizontal task bar
  222.         if(rcTaskbar.right - rcTaskbar.left >
  223.             rcTaskbar.bottom - rcTaskbar.top)
  224.         {
  225.             hclock = rcTray.bottom - rcTray.top;
  226.         }
  227.         // vertical task bar
  228.         else
  229.             wclock = rcTray.right - rcTray.left;
  230.     }
  231.     
  232.     if(m_hFont) SelectObject(hdc, hOldFont);
  233.     ReleaseDC(hwnd, hdc);
  234.     
  235.     return (hclock << 16) + wclock;
  236. }
  237.  
  238. /*------------------------------------------------
  239.    create offscreen buffer
  240. --------------------------------------------------*/
  241. void CreateClockDC(HWND hwnd)
  242. {
  243.     RECT rc;
  244.     COLORREF col;
  245.     HDC hdc;
  246.     
  247.     ClearClockDC();
  248.     
  249.     if(g_bNoClock) return;
  250.     
  251.     GetClientRect(hwnd, &rc);
  252.     
  253.     hdc = GetDC(NULL);
  254.     
  255.     if(!CreateOffScreenDC(hdc, &m_hdcClock, &m_hbmpClock,
  256.         rc.right, rc.bottom)) // dllutl.c
  257.     {
  258.         ReleaseDC(NULL, hdc);
  259.         return;
  260.     }
  261.     
  262.     SelectObject(m_hdcClock, m_hFont);
  263.     SetBkMode(m_hdcClock, TRANSPARENT);
  264.     
  265.     if(m_nTextPos == 1)
  266.         SetTextAlign(m_hdcClock, TA_LEFT|TA_TOP);
  267.     else if(m_nTextPos == 2)
  268.         SetTextAlign(m_hdcClock, TA_RIGHT|TA_TOP);
  269.     else
  270.         SetTextAlign(m_hdcClock, TA_CENTER|TA_TOP);
  271.     
  272.     col = m_colfore;
  273.     if(col & 0x80000000) col = GetSysColor(col & 0x00ffffff);
  274.     SetTextColor(m_hdcClock, col);
  275.     
  276.     /* ------- background -------- */
  277.     
  278.     if(m_bFillTray)
  279.     {
  280.         hwnd = GetParent(hwnd);
  281.         GetClientRect(hwnd, &rc);
  282.     }
  283.     
  284.     if(!CreateOffScreenDC(hdc, &m_hdcClockBack, &m_hbmpClockBack,
  285.         rc.right, rc.bottom)) // dllutl.c
  286.     {
  287.         ClearClockDC();
  288.         ReleaseDC(NULL, hdc);
  289.         return;
  290.     }
  291.     FillClock(hwnd, m_hdcClockBack, &rc);
  292.     
  293.     ReleaseDC(NULL, hdc);
  294. }
  295.  
  296. /*------------------------------------------------
  297.   calculate width and height of clock text
  298. --------------------------------------------------*/
  299. void GetClockTextSize(HDC hdc, const TEXTMETRIC* ptm,
  300.     const wchar_t* str, int *wout, int *hout)
  301. {
  302.     int w, h;
  303.     int heightFont;
  304.     const wchar_t *p, *sp, *ep;
  305.     SIZE sz;
  306.     
  307.     p = str; w = 0; h = 0;
  308.     
  309.     heightFont = ptm->tmHeight - ptm->tmInternalLeading;
  310.     while(*p)
  311.     {
  312.         sp = p;
  313.         while(*p && *p != 0x0d) p++;
  314.         ep = p;
  315.         if(*p == 0x0d) p += 2;
  316.         
  317.         if(GetTextExtentPoint32W(hdc, sp, ep - sp, &sz) == 0)
  318.             sz.cx = (ep - sp) * ptm->tmAveCharWidth;
  319.         if(w < sz.cx) w = sz.cx;
  320.         h += heightFont;
  321.         
  322.         if(*p) h += 2 + m_dlineheight;
  323.     }
  324.     
  325.     *wout = w; *hout = h;
  326. }
  327.  
  328. /*------------------------------------------------
  329.   draw the clock
  330. --------------------------------------------------*/
  331. void DrawClock(HWND hwnd, HDC hdc, const SYSTEMTIME* pt)
  332. {
  333.     RECT rcClock;
  334.     TEXTMETRIC tm;
  335.     int x, y, wclock, hclock, wtext, htext;
  336.     int len;
  337.     wchar_t s[BUFSIZE_FORMAT+BUFSIZE_DISP*2],
  338.         *p, *sp, *ep;
  339.     DWORD dwRop = SRCCOPY;
  340.     
  341.     if(!m_hdcClock) CreateClockDC(hwnd);
  342.     
  343.     if(!m_hdcClock) return;
  344.     
  345.     GetClientRect(hwnd, &rcClock);
  346.     wclock = rcClock.right;
  347.     hclock = rcClock.bottom;
  348.     
  349.     // copy m_hdcClockBack to m_hdcClock
  350.     CopyClockBack(hwnd, m_hdcClock, m_hdcClockBack, wclock, hclock);
  351.     
  352.     if(GetFocus() == hwnd)
  353.         DrawFocusRect(m_hdcClock, &rcClock);
  354.     
  355.     if(g_sdisp2[0]) wcscpy(s, g_sdisp2);
  356.     else if(g_sdisp1[0]) wcscpy(s, g_sdisp1);
  357.     else MakeFormat(s, pt, NULL, BUFSIZE_FORMAT);  // format.c
  358.     
  359.     if(g_scat1[0])
  360.     {
  361.         len = wcslen(s);
  362.         if(len > 0 && s[len - 1] != 0x0a && s[len - 1] != ' ')
  363.             wcscat(s, L" ");
  364.         wcscat(s, g_scat1);
  365.     }
  366.     if(g_scat2[0])
  367.     {
  368.         len = wcslen(s);
  369.         if(len > 0 && s[len - 1] != 0x0a && s[len - 1] != ' ')
  370.             wcscat(s, L" ");
  371.         wcscat(s, g_scat2);
  372.     }
  373.     
  374.     GetTextMetrics(m_hdcClock, &tm);
  375.     
  376.     GetClockTextSize(m_hdcClock, &tm, s, &wtext, &htext);
  377.     
  378.     y = (hclock - htext)/2 - tm.tmInternalLeading/2 + m_dvpos;
  379.     
  380.     if(m_nTextPos == 1)
  381.         x = (tm.tmAveCharWidth * 2) / 3;
  382.     else if(m_nTextPos == 2)
  383.         x = wclock - (tm.tmAveCharWidth * 2) / 3;
  384.     else
  385.         x = wclock / 2;
  386.     
  387.     p = s;
  388.     while(*p)
  389.     {
  390.         sp = p;
  391.         while(*p && *p != 0x0d) p++;
  392.         ep = p;
  393.         if(*p == 0x0d) p += 2;
  394.         TextOutW(m_hdcClock, x, y, sp, ep - sp);
  395.         
  396.         if(*p) y += tm.tmHeight - tm.tmInternalLeading
  397.                     + 2 + m_dlineheight;
  398.     }
  399.     
  400.     if(g_nBlink > 0 && (g_nBlink % 2) == 0) dwRop = NOTSRCCOPY;
  401.     
  402.     BitBlt(hdc, 0, 0, wclock, hclock, m_hdcClock, 0, 0, dwRop);
  403.     
  404.     if(wtext + tm.tmAveCharWidth * 2 + m_dwidth > m_ClockWidth)
  405.     {
  406.         m_ClockWidth = wtext + tm.tmAveCharWidth * 2 + m_dwidth;
  407.         PostMessage(GetParent(GetParent(hwnd)), WM_SIZE, SIZE_RESTORED, 0);
  408.         InvalidateRect(GetParent(GetParent(hwnd)), NULL, TRUE);
  409.     }
  410. }
  411.  
  412. /*------------------------------------------------
  413.   copy background image
  414.   from m_hdcClockBack to m_hdcClock
  415. --------------------------------------------------*/
  416. void CopyClockBack(HWND hwnd, HDC hdcDest, HDC hdcSrc, int w, int h)
  417. {
  418.     int xsrc = 0, ysrc = 0;
  419.     
  420.     if(m_bFillTray)
  421.     {
  422.         HWND hwndTray;
  423.         RECT rc;
  424.         POINT pt;
  425.         
  426.         hwndTray = GetParent(hwnd);
  427.         GetWindowRect(hwnd, &rc);
  428.         pt.x = rc.left; pt.y = rc.top;
  429.         ScreenToClient(hwndTray, &pt);
  430.         xsrc = pt.x; ysrc = pt.y;
  431.     }
  432.     
  433.     BitBlt(hdcDest, 0, 0, w, h, hdcSrc, xsrc, ysrc, SRCCOPY);
  434. }
  435.  
  436. /*------------------------------------------------
  437.   paint background of clock
  438. --------------------------------------------------*/
  439. void FillClock(HWND hwnd, HDC hdc, const RECT *prc)
  440. {
  441.     HBRUSH hbr;
  442.     COLORREF col;
  443.     
  444.     if(!m_fillbackcolor)
  445.     {
  446.         RECT rc, rcTray;
  447.         GetWindowRect(hwnd, &rc);
  448.         GetWindowRect(GetParent(hwnd), &rcTray);
  449.         CopyParentSurface(hwnd, hdc, 0, 0, prc->right, prc->bottom,
  450.             rc.left - rcTray.left, rc.top - rcTray.top);
  451.     }
  452.     else if(m_colback == m_colback2 || !(g_winver&(WIN98|WIN2000)))
  453.     {
  454.         col = m_colback;
  455.         if(col & 0x80000000) col = GetSysColor(col & 0x00ffffff);
  456.         hbr = CreateSolidBrush(col);
  457.         FillRect(hdc, prc, hbr);
  458.         DeleteObject(hbr);
  459.     }
  460.     else
  461.     {
  462.         COLORREF col2;
  463.         
  464.         col = m_colback;
  465.         if(col & 0x80000000) col = GetSysColor(col & 0x00ffffff);
  466.         col2 = m_colback2;
  467.         if(col2 & 0x80000000) col2 = GetSysColor(col2 & 0x00ffffff);
  468.         
  469.         GradientFillClock(hdc, prc, col, col2, m_grad);
  470.     }
  471. }
  472.  
  473. /*------------------------------------------------
  474.   smooth shaded background
  475. --------------------------------------------------*/
  476. void GradientFillClock(HDC hdc, const RECT* prc,
  477.     COLORREF col1, COLORREF col2, DWORD grad)
  478. {
  479.     TRIVERTEX vert[2];
  480.     GRADIENT_RECT gRect;
  481.     
  482.     vert[0].x      = prc->left;
  483.     vert[0].y      = prc->top;
  484.     vert[0].Red    = (COLOR16)((int)GetRValue(col1) * 256);
  485.     vert[0].Green  = (COLOR16)((int)GetGValue(col1) * 256);
  486.     vert[0].Blue   = (COLOR16)((int)GetBValue(col1) * 256);
  487.     vert[0].Alpha  = 0x0000;
  488.     vert[1].x      = prc->right;
  489.     vert[1].y      = prc->bottom; 
  490.     vert[1].Red    = (COLOR16)((int)GetRValue(col2) * 256);
  491.     vert[1].Green  = (COLOR16)((int)GetGValue(col2) * 256);
  492.     vert[1].Blue   = (COLOR16)((int)GetBValue(col2) * 256);
  493.     vert[1].Alpha  = 0x0000;
  494.     gRect.UpperLeft  = 0;
  495.     gRect.LowerRight = 1;
  496.     
  497.     // newapi.c
  498.     MyGradientFill(hdc, vert, 2, &gRect, 1, grad);
  499. }
  500.  
  501.